package com.boc;

import java.io.*;
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.Stack;
import java.util.regex.*;

public class IBatisToMyBatisConverterNested {
    public static void main(String[] args) throws IOException {
        String inputFilePath = "ibatis.xml"; // 输入文件路径
        String outputFilePath = "mybatis.xml"; // 输出文件路径

        // 读取 XML 文件内容
        String xmlContent = Files.readString(Paths.get(inputFilePath), StandardCharsets.UTF_8);

        // 移除现有文件头并转换内容
        String cleanedContent = removeFileHeader(xmlContent);
        String convertedContent = convertIBatisToMyBatis(cleanedContent);

        // 替换 <sqlMap> 为 <mapper> 并修改 namespace
        convertedContent = replaceSqlMapWithMapper(convertedContent);

        // 替换结尾的 </sqlMap> 为 </mapper>
        convertedContent = convertedContent.replaceAll("</sqlMap>", "</mapper>");

        // 处理 resultMap 标签中的 class 属性替换为 type
        convertedContent = replaceResultMapClassWithType(convertedContent);

        // 处理 parameterClass 属性替换为 parameterType
        convertedContent = replaceParameterClassWithParameterType(convertedContent);

        // 在转换后的内容之前添加新的文件头
        String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n";

        // 将文件头和转换后的内容合并
        String finalContent = header + convertedContent;

        // 将文件头和转换后的内容写入文件
        Files.writeString(Paths.get(outputFilePath), finalContent, StandardCharsets.UTF_8);

        System.out.println("Conversion completed! Output saved to " + outputFilePath);
    }

    // 移除现有的文件头
    private static String removeFileHeader(String xmlContent) {
        // 正则匹配 XML 文件头部分
        String headerPattern = "^<\\?xml[\\s\\S]*?\\?>\\s*<!DOCTYPE[\\s\\S]*?\\s*>\\s*";
        return xmlContent.replaceAll(headerPattern, "");
    }

    // 替换 <sqlMap> 为 <mapper> 并修改 namespace
    private static String replaceSqlMapWithMapper(String xmlContent) {
        // 正则匹配 <sqlMap> 标签并提取 namespace 属性
        Pattern sqlMapPattern = Pattern.compile("<sqlMap\\s+namespace=\"([^\"]+)\"[^>]*>", Pattern.DOTALL);
        Matcher matcher = sqlMapPattern.matcher(xmlContent);

        // 替换每一个 <sqlMap> 标签
        StringBuffer result = new StringBuffer();
        while (matcher.find()) {
            // 获取原始 namespace 值
            String originalNamespace = matcher.group(1);

            // 去掉 sql_ 前缀并修改 namespace
            String newNamespace = "com.bocsoft.csar.sts.application.bootstrap.mapper.csar." +
                    originalNamespace.replace("sql_", "") + "Dao";

            // 替换为新的 <mapper> 标签
            String newSqlMapTag = "<mapper namespace=\"" + newNamespace + "\">";
            matcher.appendReplacement(result, Matcher.quoteReplacement(newSqlMapTag));
        }
        matcher.appendTail(result);

        return result.toString();
    }

    // 替换 resultMap 中的 class 属性为 type
    private static String replaceResultMapClassWithType(String xmlContent) {
        // 正则匹配 <resultMap> 标签并提取 class 属性
        Pattern resultMapPattern = Pattern.compile(
                "<resultMap\\s+[^>]*class=\"([^\"]+)\"[^>]*>", Pattern.DOTALL);
        Matcher matcher = resultMapPattern.matcher(xmlContent);

        StringBuffer result = new StringBuffer();
        while (matcher.find()) {
            // 获取原始 class 值
            String className = matcher.group(1);

            // 提取 className 中最后的部分（去掉包名）
            String baseName = className.substring(className.lastIndexOf('.') + 1);

            // 构建新的 type 值
            String newType = "com.bocsoft.csar.sts.application.bootstrap.entity.csar." + baseName;

            // 替换 class 属性为 type，并修改其值
            String newResultMapTag = matcher.group(0).replace("class=\"" + className + "\"", "type=\"" + newType + "\"");
            matcher.appendReplacement(result, Matcher.quoteReplacement(newResultMapTag));
        }
        matcher.appendTail(result);

        return result.toString();
    }

    // 替换 parameterClass 属性为 parameterType
    // 替换 parameterClass 属性为 parameterType
    private static String replaceParameterClassWithParameterType(String xmlContent) {
        // 正则匹配带有 parameterClass 属性的标签，适应多种标签情况
        Pattern parameterClassPattern = Pattern.compile(
                "<(\\w+)([^>]*?)parameterClass=\"([^\"]+)\"([^>]*?)>", Pattern.DOTALL);
        Matcher matcher = parameterClassPattern.matcher(xmlContent);

        StringBuffer result = new StringBuffer();
        while (matcher.find()) {
            // 提取标签名、属性值和其他属性
            String tagName = matcher.group(1); // 标签名
            String beforeParamClass = matcher.group(2); // 参数前部分
            String parameterClassValue = matcher.group(3); // parameterClass 属性值
            String afterParamClass = matcher.group(4); // 参数后部分

            // 替换为 parameterType
            String newTag = String.format("<%s%sparameterType=\"%s\"%s>",
                    tagName, beforeParamClass, parameterClassValue, afterParamClass);

            matcher.appendReplacement(result, Matcher.quoteReplacement(newTag));
        }
        matcher.appendTail(result);

        return result.toString();
    }


    private static String convertIBatisToMyBatis(String xmlContent) {
        // 替换占位符 #property# 为 #{property}
        xmlContent = xmlContent.replaceAll("#(\\w+)#", "#{$1}");

        // 使用递归替换 <isNotEmpty> 标签为 <if>
        xmlContent = replaceIsNotEmptyWithIf(xmlContent);

        return xmlContent;
    }

    // 替换 <isNotEmpty> 标签为 <if> 标签，不使用递归
    public static String replaceIsNotEmptyWithIf(String xmlContent) {

        StringBuilder result = new StringBuilder();
        Stack<Integer> stack = new Stack<>();
        StringBuilder buffer = new StringBuilder();

        // 使用正则匹配 <isNotEmpty> 和 </isNotEmpty>
        Pattern tagPattern = Pattern.compile("<(/?)isNotEmpty(\\s+[^>]*)?>");
        Matcher matcher = tagPattern.matcher(xmlContent);

        int lastMatchEnd = 0;

        while (matcher.find()) {
            // 将匹配之前的内容添加到结果中
            if (stack.isEmpty()) {
                result.append(xmlContent, lastMatchEnd, matcher.start());
            } else {
                buffer.append(xmlContent, lastMatchEnd, matcher.start());
            }

            String tagName = matcher.group(1); // "/" 表示结束标签
            String attributes = matcher.group(2); // 获取属性内容

            if (tagName == null || tagName.isEmpty()) {
                // 起始标签
                stack.push(result.length() + buffer.length());
                buffer.append("<if");
                // 替换属性为 MyBatis 格式
                String prepend = getAttribute(attributes, "prepend");
                String property = getAttribute(attributes, "property");
                buffer.append(String.format(" test=\"%s != null and %s != ''\">%s", property, property, prepend != null ? prepend : ""));
            } else {
                // 结束标签
                int start = stack.pop();
                if (stack.isEmpty()) {
                    result.append(buffer.toString());
                    result.append("</if>");
                    buffer.setLength(0);
                } else {
                    buffer.append("</if>");
                }
            }

            lastMatchEnd = matcher.end();
        }

        // 处理剩余内容
        if (stack.isEmpty()) {
            result.append(xmlContent, lastMatchEnd, xmlContent.length());
        }

        return result.toString();
    }

    private static String getAttribute(String attributes, String attributeName) {
        Pattern attrPattern = Pattern.compile(attributeName + "=\"([^\"]+)\"");
        Matcher attrMatcher = attrPattern.matcher(attributes);
        if (attrMatcher.find()) {
            return attrMatcher.group(1);
        }
        return null;
    }

}
